import os
import pandas as pd
import preprocess
import cv2
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid1 import ImageGrid
import numpy as np
from keras.applications.vgg16 import VGG16
from keras.applications.vgg16 import preprocess_input, decode_predictions
pd.set_option("display.max_rows",999)
np.random.seed(42)
DATA_DIR_PATH = preprocess.DATA_DIR_PATH
NUM_CLASSES = 120
labels = pd.read_csv(os.path.join(preprocess.DATA_DIR, 'labels.csv'))
def get_img_cls_from_id(img_id):
return labels[labels.id == img_id]['breed'].values[0]
labels.groupby('breed').count().sort_values(by='id', ascending=False)
def read_image_as_rbg(img_id = None, shape = None):
#img_id = '0a0c223352985ec154fd604d7ddceabd'
img_BGR = cv2.imread(os.path.join(DATA_DIR_PATH, 'train', f'{img_id}.jpg'))
if shape is not None:
img_BGR = cv2.resize(img_BGR, shape)
return cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB)
#labels[labels.breed == 'scottish_deerhound'].id.tolist()[:5]
#4 Breed I chose fo fun
breeds = ['scottish_deerhound', 'maltese_dog', 'pomeranian', 'cocker_spaniel']
NUM_SAMPLE_PER_BREED = 6
fig = plt.figure(1, figsize=(32, 32))
grid = ImageGrid(fig, 111, nrows_ncols=(len(breeds), NUM_SAMPLE_PER_BREED), axes_pad=0.05)
idx = 0
for breed in breeds:
for img_id in labels[labels.breed == breed].id.tolist()[:6]:
ax = grid[idx]
img = read_image_as_rbg(img_id=img_id)
ax.imshow(img)
ax.axis('off')
idx += 1
plt.show()
We can use the weights of any model that's been trained on imagenet keras comes with some pre-trained "classical" models that are trained on existing datasets VGG16 is a "16-layer network used by the VGG team in the ILSVRC-2014 competition"
TODO: show image of the model
model_vgg16 = VGG16(weights='imagenet')
img_id = '0042188c895a2f14ef64a918ed9c7b64'
img = read_image_as_rbg(img_id=img_id, shape = (224, 224))
print(img.shape, img.max(), img.min())
x = preprocess_input(np.expand_dims(img.copy() + 0.0, axis = 0)) #return (1, 224, 224, 3)
preds = model_vgg16.predict(x)
res = decode_predictions(preds, top=2)
res
def plot_image_and_labels(img_arr, true_cls, pred1, pred2):
_, cls1, prob1 = pred1
_,cls2, prob2 = pred2
# cls, prob = 'Scottish_deerhound', 0.78298694
# breed = 'scottish'
plt.imshow(img)
plt.text(10, 200, 'Predicted: %s (%.3f)' % (cls1 , prob1), color='w', backgroundcolor='k', alpha=0.8)
plt.text(10, 220, 'Predicted: %s (%.3f)' % (cls2 , prob2), color='w', backgroundcolor='k', alpha=0.8)
plt.text(10, 15, 'LABEL: %s' % breed, color='k', backgroundcolor='w', alpha=0.8)
plt.axis('off')
plt.show()
plot_image_and_labels(x, get_img_cls_from_id(img_id), pred1 = res[0][0], pred2=res[0][1])
NUM_SAMPLE_PER_BREED = 6
fig = plt.figure(1, figsize=(32, 32))
grid = ImageGrid(fig, 111, nrows_ncols=(len(breeds), NUM_SAMPLE_PER_BREED), axes_pad=0.05)
idx = 0
for breed in breeds:
print('starting', breed)
for img_id in labels[labels.breed == breed].id.tolist()[:6]:
ax = grid[idx]
img = read_image_as_rbg(img_id=img_id, shape = (224, 224))
x = preprocess_input(np.expand_dims(img.copy().astype(float), axis = 0)) #return (1, 224, 224, 3)
preds = model_vgg16.predict(x)
_, cls, prob = decode_predictions(preds, top=1)[0][0]
ax.imshow(img)
ax.text(10, 200, 'Predicted: %s (%.3f)' % (cls , prob), color='w', backgroundcolor='k', alpha=0.8)
ax.text(10, 15, 'LABEL: %s' % breed, color='k', backgroundcolor='w', alpha=0.8)
ax.axis('off')
idx += 1
plt.show()
tmp = np.vstack( (np.array([1,1,1]), np.array([0,0,0])) )
tmp.sum(axis = 0)
x_train_list_id = []
y_train_labels = None
BREED_TO_IDX_MAP = { breed:idx for idx, breed in enumerate(breeds)}
IDX_TO_BREED_MAP = { idx:breed for idx, breed in enumerate(breeds)}
for idx, breed in enumerate(breeds):
BREED_TO_IDX_MAP[breed] = idx
breed_list = labels[labels.breed == breed].id.tolist()
num_ids = len(breed_list)
breed_y = np.zeros((len(breed_list), len(breeds)))
breed_y[:, idx] = 1 #mark response for this breed at this index
x_train_list_id.extend( breed_list )
print(len(breed_list), breed_y.shape)
if y_train_labels is None:
y_train_labels = breed_y
else:
y_train_labels = np.vstack( (y_train_labels, breed_y) )
print(BREED_TO_IDX_MAP)
print(IDX_TO_BREED_MAP)
print(len(x_train_list_id), y_train_labels.shape, y_train_labels.sum(axis = 0))
def decode_arr(input_arr):
"""
input_arr: vector of size 4
"""
assert input_arr.shape == (4,), 'input wrong shape'
return IDX_TO_BREED_MAP[input_arr.argmax()]
def get_image_matrix_from_ids(list_of_ids, output_size = (200, 200)):
img_matrix = np.zeros((len(list_of_ids), output_size[0], output_size[1], 3), dtype='float32') #stores all of the images in a 4 dim tensor
for idx, img_id in enumerate(list_of_ids):
img = read_image_as_rbg(img_id=img_id, shape=output_size)
img_matrix[idx] = img
return img_matrix
x_train = get_image_matrix_from_ids(x_train_list_id)
def normalize_images(img_tensor):
return (img_tensor - 128.0)/ 128.0 #scales all values to -1.0 to 1.0
NUM_SAMPLES = x_train.shape[0]
idx_arr = np.arange(NUM_SAMPLES)
np.random.shuffle(idx_arr)
print('sample of random array', idx_arr[:25])
train_arr = idx_arr[:int(NUM_SAMPLES * 0.8)]
valid_arr = idx_arr[int(NUM_SAMPLES * 0.8):]
X_train_arr = x_train[train_arr]
X_valid_arr = x_train[valid_arr]
y_train_arr = y_train_labels[train_arr]
y_valid_arr = y_train_labels[valid_arr]
print(X_train_arr.shape, y_train_arr.shape)
print(y_train_arr.sum(axis = 0))
print(y_valid_arr.sum(axis = 0))
for i in range(20):
plt.imshow(X_train_arr[i].astype('uint8'))
plt.show()
print(decode_arr(y_train_arr[i]))
decode_arr(y_train_arr[20])
import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD
import time
#model.reset_states()
#based on mnist architecture and way too slow to train
model = Sequential()
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(200, 200, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2))) #usually this variable is 2, 2
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, activation='softmax'))
sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.summary()
#model.fit(x_train, y_train, batch_size=32, epochs=10)
#score = model.evaluate(x_test, y_test, batch_size=32)
X_train_arr_norm = normalize_images(X_train_arr)
X_valid_arr_norm = normalize_images(X_valid_arr)
def make_confusion_matrix(pred, actual, num_classes):
cm = np.zeros((num_classes, num_classes))
num_results = pred.shape[0]
for i in range(num_results):
cm[pred[i], actual[i]] += 1.0
return cm
start = time.time()
num_round = 20
num_epochs_per_round = 10
print('Total Number of Epochs')
for i in range(num_round):
print('Training Step: ', i)
model.fit(X_train_arr_norm, y_train_arr, batch_size=32, epochs=num_epochs_per_round)
pred_prob = model.predict_proba(X_valid_arr_norm)
acc = (pred_prob.argmax(axis = 1) == y_valid_arr.argmax(axis = 1)).astype('float32').mean()
loss = model.evaluate(X_valid_arr, y_valid_arr, batch_size=32)
#print(pred_prob.round(3))
print('Summary Stats on Predictions:')
print(pred_prob.min(axis = 0))
print(pred_prob.max(axis = 0))
print(pred_prob.mean(axis = 0))
print(pred_prob.std(axis = 0))
print(make_confusion_matrix(pred_prob.argmax(axis = 1), y_valid_arr.argmax(axis = 1), 4))
print('Prediction Validation Accuracy and Loss', acc, loss)
print('Total Elapsed Time', time.time() - start)
model.save('dog_breed_demo-arch-1-epoch-200.h5')
import json
json.dump(model.to_json(), open('arch-1.json', 'w'))